perm filename FIXUP.L[FTL,LSP] blob
sn#826388 filedate 1986-10-21 generic text, type T, neo UTF8
;;;-*-Mode:LISP; Package: PCL; Base:10; Syntax:Common-lisp; Patch-File: Yes -*-
;;;
;;; *************************************************************************
;;; Copyright (c) 1985 Xerox Corporation. All rights reserved.
;;;
;;; Use and copying of this software and preparation of derivative works
;;; based upon this software are permitted. Any distribution of this
;;; software or derivative works must comply with all applicable United
;;; States export control laws.
;;;
;;; This software is made available AS IS, and Xerox Corporation makes no
;;; warranty about the software, its performance or its conformity to any
;;; specification.
;;;
;;; Any person obtaining a copy of this software is requested to send their
;;; name and post office or electronic mail address to:
;;; CommonLoops Coordinator
;;; Xerox Artifical Intelligence Systems
;;; 2400 Hanover St.
;;; Palo Alto, CA 94303
;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
;;;
;;; Suggestions, comments and requests for improvements are also welcome.
;;; *************************************************************************
;;;
(in-package 'pcl)
(eval-when (compile load eval)
(setf (symbol-function 'expand-defmeth)
(symbol-function 'real-expand-defmeth)))
(eval-when (load)
(clrhash *discriminator-name-hash-table*)
(fix-early-defmeths)
(setq *error-when-defining-method-on-existing-function* t))
(eval-when (compile load eval)
(setq *real-methods-exist-p* t))
;;
;;;;;; Pending defmeths which I couldn't do before.
;;
(eval-when (load eval)
(setf (discriminator-named 'print-instance) ())
(make-specializable 'print-instance :arglist '(instance stream depth)))
(defmeth print-instance ((instance object) stream depth)
(let ((length (if (numberp *print-length*) (* *print-length* 2) nil)))
(format stream "#S(~S" (class-name (class-of instance)))
(iterate ((slot-or-value in (all-slots instance))
(slotp = t (not slotp)))
(when (numberp length)
(cond ((<= length 0) (format stream " ...") (return ()))
(t (decf length))))
(princ " " stream)
(let ((*print-level* (cond ((null *print-level*) ())
(slotp 1)
(t (- *print-level* depth)))))
(if (and *print-level* (<= *print-level* 0))
(princ "#" stream)
(prin1 slot-or-value stream))))
(princ ")" stream)))
(defmeth print-instance ((class essential-class) stream depth)
(named-object-print-function class stream depth))
(eval-when (load)
(define-meta-class essential-class (lambda (x) (%instance-ref x 0)))
(defmeth class-slots ((class essential-class))
())
(defmeth make-instance ((class essential-class))
(let ((primitive-instance
(%make-instance (class-named 'essential-class)
(1+ (length (class-slots class))))))
(setf (%instance-ref primitive-instance 0) class)
primitive-instance))
(defmeth get-slot-using-class ((class essential-class) object slot-name)
(let ((pos (position slot-name (class-slots class) :key #'slotd-name)))
(if pos
(%instance-ref object (1+ pos))
(slot-missing ;class
object slot-name))))
(defmeth put-slot-using-class ((class essential-class)
object
slot-name
new-value)
(let ((pos (position slot-name (class-slots class) :key #'slotd-name)))
(if pos
(setf (%instance-ref object (1+ pos)) new-value)
(slot-missing ;class
object slot-name))))
(defmeth optimize-get-slot ((method essential-method)
(class essential-class)
form)
form)
(defmeth optimize-setf-of-get-slot ((method essential-method)
(class essential-class)
form)
form)
(defmeth make-slotd ((class essential-class) &rest keywords-and-options)
(apply #'make-slotd--essential-class keywords-and-options))
(defmeth add-named-class ((proto-class essential-class) name
local-supers
local-slot-slotds
extra)
;; First find out if there is already a class with this name.
;; If there is, call class-for-redefinition to get the class
;; object to use for the new definition. If there is no exisiting
;; class we just make a new instance.
(let* ((existing (class-named name t))
(class (if existing
(class-for-redefinition existing proto-class name
local-supers local-slot-slotds
extra)
(make (class-of proto-class)))))
(setq local-supers
(mapcar
#'(lambda (ls)
(or (class-named ls t)
(error "~S was specified as the name of a local-super~%~
for the class named ~S. But there is no class~%~
class named ~S." ls name ls)))
local-supers))
(setf (class-name class) name)
; (setf (class-ds-options class) extra) ;This is NOT part of the
; ;standard protocol.
(add-class class local-supers local-slot-slotds extra)
(setf (class-named name) class)
name))
(defmeth supers-changed ((class essential-class)
old-local-supers
old-local-slots
extra
top-p)
(ignore old-local-supers old-local-slots top-p)
(let ((cpl (compute-class-precedence-list class
(class-local-supers class))))
(setf (class-class-precedence-list class) cpl)
; (update-slots--class class cpl) ;This is NOT part of
; ;the essential-class
; ;protocol.
(dolist (sub-class (class-direct-subclasses class))
(supers-changed sub-class
(class-local-supers sub-class)
(class-local-slots sub-class)
extra
nil))
; (when top-p ;This is NOT part of
; (update-method-inheritance class old-local-supers));the essential-class
; ;protocol.
))
(defmeth slots-changed ((class essential-class)
old-local-slots
extra
top-p)
(ignore top-p old-local-slots)
;; When this is called, class should have its local-supers and
;; local-slots slots filled in properly.
; (update-slots--class class (class-class-precedence-list class))
(dolist (sub-class (class-direct-subclasses class))
(slots-changed sub-class (class-local-slots sub-class) extra nil)))
(defmeth method-equal (method argument-specifiers options)
(equal argument-specifiers (method-type-specifiers method)))
(defmeth methods-combine-p ((d essential-discriminator))
nil)
)
;;
;;;;;;
;;
(defmacro run-super ()
(if (null (boundp '*current-discriminator-name*))
(progn (warn "Using run-super outside of a defmeth~%~
At run time this will generate an error.")
`(error "Using run-super outside of a defmeth."))
(let ((type-specs (method-type-specifiers *current-method*)))
(cond ((null type-specs)
(warn "Using run-super inside of a default method~%~
At run time this will generate an error.")
`(error "Using run-super from inside a default method."))
(t
`(run-super-internal
(load-time-eval (discriminator-named ',*current-discriminator-name*))
(load-time-eval (or *current-method*
(find-method
(discriminator-named ',*current-discriminator-name*)
',(unparse-type-specifiers *current-method*)
()
t)))
. ,(method-arglist *current-method*)))))))
(defun run-super-internal (discriminator current-method &rest args)
(let ((type-specifiers (method-type-specifiers current-method))
(most-specific nil)
(most-specific-type-specifiers ())
(dispatch-order (get-slot--class discriminator 'dispatch-order)))
(iterate ((method in (discriminator-methods discriminator)))
(let ((method-type-specifiers (method-type-specifiers method))
(temp ()))
(and (every #'(lambda (arg type-spec)
(or (eq type-spec 't)
(memq type-spec
(get-slot--class
(class-of arg) 'class-precedence-list))))
args method-type-specifiers)
(eql 1 (setq temp (compare-type-specifier-lists type-specifiers
method-type-specifiers
()
args
()
dispatch-order)))
(or (null most-specific)
(eql 1 (setq temp (compare-type-specifier-lists
method-type-specifiers
most-specific-type-specifiers
()
args
()
dispatch-order))))
(setq most-specific method
most-specific-type-specifiers method-type-specifiers))))
(if (or most-specific
(setq most-specific (discriminator-default-method discriminator)))
(apply (method-function most-specific) args)
(error "no super method found"))))